import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { get } from 'lodash-es'
import { FileUtils } from '@sat/shared-utils'
import type { Awaitable } from 'element-plus/es/utils'
import type {
  UploadFile,
  UploadFiles,
  UploadRawFile,
  UploadUserFile,
} from 'element-plus'

export interface Options {
  action: string
  token?: string
  accept?: string
  maxSizeByte?: number
  _props?: {
    // 对应关系
    url?: string[] | string
    code?: string[] | string
    name?: string[] | string
    message?: string[] | string
  }
  // TODO type
  onPreview?: (file: UploadFile) => void
  onRemove?: (file: UploadFile, fileList: UploadFiles) => void
  onSuccess?: (response: any, file: UploadFile, fileList: UploadFiles) => void
  onChange?: (file: UploadFile, fileList: UploadFiles) => void
  onExceed?: (files: File[], uploadFiles: UploadUserFile[]) => void
  beforeUpload?: (
    file: UploadRawFile,
  ) => Awaitable<void | undefined | null | boolean | File | Blob>
}
/**
 * @description 仅限单文件上传
 */
export function useUpload(options: Options) {
  const refValue = ref<string>()
  const refResponse = ref<any>()
  const refFileList = ref<any[]>([])
  const action = options.action
  const accept = options.accept ?? ''
  const fileName = ref<string>()
  return {
    fileName,
    refValue,
    refResponse,
    refFileList,
    action,
    accept,
    auth: {
      'Authorization': options.token,
      'X-Requested-With': 'XMLHttpRequest',
    },
    onPreview: (file: UploadFile) => {
      if (options.onPreview) {
        // 重写该方法
        options.onPreview(file)
        return
      }
      ElMessageBox.confirm('想要查看需下载该文件, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        if (file.raw) {
          FileUtils.downloadFile(file.raw)
          return
        }
        const url = file.url
        window.open(url)
      })
    },
    onRemove: (file: UploadFile, fileList: UploadFiles) => {
      refValue.value = ''
      fileName.value = ''
      refResponse.value = null
      if (options.onRemove)
        options.onRemove(file, fileList)
    },
    onSuccess: (response: any, file: UploadFile, fileList: UploadFiles) => {
      refResponse.value = response
      fileName.value = file.name
      if (get(response, options._props?.code ?? 'code') == 200) {
        refValue.value = get(response, options._props?.url ?? 'url')
        refFileList.value = [
          {
            raw: file.raw,
            name: get(response, options._props?.username ?? 'name') || file.name,
            url: get(response, options._props?.url ?? 'url'),
          },
        ]
      }
      else {
        ElMessage.error(
          get(response, options._props?.message ?? 'message') ?? '上传失败',
        )
        fileList.splice(0, 1)
      }
      if (options.onSuccess)
        options.onSuccess(response, file, fileList)
    },
    onExceed: (files: File[], uploadFiles: UploadUserFile[]) => {
      if (options.onExceed) {
        // 重写该方法
        options.onExceed(files, uploadFiles)
        return
      }
      ElMessage.warning('文件超出最大个数限制')
    },
    beforeUpload: (file: UploadRawFile) => {
      const suffix = FileUtils.getSuffix(file.name)
      if (!accept.includes(suffix)) {
        ElMessage.warning(`文件格式不正确，请上传${accept}格式的文件`)
        return false
      }
      if (file.size && options.maxSizeByte && file.size > options.maxSizeByte) {
        const gb = options.maxSizeByte / 1024 / 1024 / 1024
        const mb = options.maxSizeByte / 1024 / 1024
        const kb = options.maxSizeByte / 1024
        let tip = `${gb}Gb`
        if (gb < 1)
          tip = `${mb}Mb`

        if (mb < 1)
          tip = `${kb}kb`

        ElMessage.warning(
          `您上传的文件已超出上传最大限制：${tip}，请重新选择文件`,
        )
        return false
      }
      if (options.beforeUpload)
        return options.beforeUpload(file)
    },
    onChange: (file: UploadFile, fileList: UploadFiles) => {
      if (options.onChange)
        options.onChange(file, fileList)
    },
  }
}
